package db

import (
	"database/sql"
	"fmt"
	"log"
	"sync"
	"time"

	"gitee.com/li-zhenyi/yi-nian-zhi-jian/backend/internal/config"
	_ "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var (
	mysqlDB   *gorm.DB
	sqlDB     *sql.DB
	mysqlOnce sync.Once
)

// InitMySQL 初始化MySQL数据库连接
// 这个函数使用单例模式确保全局只有一个数据库连接实例
func InitMySQL(cfg *config.Config) (*gorm.DB, error) {
	// 构建DSN (Data Source Name)
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		cfg.MySQL.Username,
		cfg.MySQL.Password,
		cfg.MySQL.Host,
		cfg.MySQL.Port,
		cfg.MySQL.Database,
	)

	return InitMySQLWithDSN(dsn)
}

// InitMySQLWithDSN 使用指定的DSN初始化MySQL数据库连接
// 这个函数允许直接传入DSN字符串，适用于需要连接到不同数据库或使用不同用户的场景
func InitMySQLWithDSN(dsn string) (*gorm.DB, error) {
	var err error
	mysqlOnce.Do(func() {
		// 创建gorm数据库连接
		mysqlDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
			Logger: logger.Default.LogMode(logger.Info), // 设置日志模式为Info
		})
		if err != nil {
			log.Printf("MySQL连接失败: %v", err)
			return
		}

		// 获取通用数据库对象
		sqlDB, err = mysqlDB.DB()
		if err != nil {
			log.Printf("获取SQL DB对象失败: %v", err)
			return
		}

		// 设置连接池参数
		sqlDB.SetMaxOpenConns(100)              // 设置最大打开的连接数
		sqlDB.SetMaxIdleConns(20)               // 设置闲置的连接数
		sqlDB.SetConnMaxLifetime(time.Hour * 4) // 设置连接可复用的最大时间
		sqlDB.SetConnMaxIdleTime(time.Hour * 2) // 设置连接最大空闲时间

		// 验证连接
		if err = sqlDB.Ping(); err != nil {
			log.Printf("MySQL ping失败: %v", err)
			return
		}

		log.Println("MySQL连接成功")
	})

	return mysqlDB, err
}

// GetMySQLDB 获取MySQL数据库连接实例
// 这个函数返回已初始化的数据库连接实例
func GetMySQLDB() *gorm.DB {
	return mysqlDB
}

// CloseMySQL 关闭MySQL数据库连接
// 在应用程序退出时调用这个函数来释放资源
func CloseMySQL() error {
	if sqlDB != nil {
		return sqlDB.Close()
	}
	return nil
}